package com.shisan.tingshu.common.config.date;

import com.shisan.tingshu.common.execption.ShisanException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.deser.std.DateDeserializers;
import com.fasterxml.jackson.databind.ser.std.DateSerializer;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

/**
 * 自定义一个序列化和反序列化器实现对时间格式和时区的转换
 */
@Configuration
public class CustomerDateHandler implements Jackson2ObjectMapperBuilderCustomizer {
    // 自定义处理
    @Override
    public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {

        // 创建时间模版对象
        JavaTimeModule javaTimeModule = new JavaTimeModule();

        // 对时间格式进行序列化
        javaTimeModule.addSerializer(Date.class, new DateSerializer() {
            // 自定义对时间类型做序列化操作
            /**
             * @param value Value to serialize; can <b>not</b> be null. 即要序列化的对象里面的Date类型的字段以其值
             * @param g Generator used to output resulting Json content 即json生成器：用来负责将数据输出到json中
             * @param provider Provider that can be used to get serializers for 暂时用不到
             *   serializing Objects value contains, if any.
             * @throws IOException
             */
            @Override
            public void serialize(Date value, JsonGenerator g, SerializerProvider provider) throws IOException {
                // 处理日期时间格式
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                // 处理时间时区
                simpleDateFormat.setTimeZone(TimeZone.getTimeZone("GMT+8"));
                // 将时间格式化后输出
                String format = simpleDateFormat.format(value);
                g.writeString(format);
            }
        });

        // 对时间格式进行反序列化
        javaTimeModule.addDeserializer(Date.class, new DateDeserializers.DateDeserializer() {
            /**
             * @param p Parsed used for reading JSON content。即json解析器，用来解析json数据
             * @param ctxt Context that can be used to access information about
             * this deserialization activity.
             * @return
             * @throws IOException
             */
            @Override
            public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
                // 获取到时间字符串
                String timeStr = p.getText();
                // 处理时间格式
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                // 处理时间时区
                simpleDateFormat.setTimeZone(TimeZone.getTimeZone("GMT+8"));
                try {
                    Date parseDate = simpleDateFormat.parse(timeStr);
                    return parseDate;
                } catch (ParseException e) {
                    throw new ShisanException(201, "时间格式不对，无法解析");
                }
            }
        });

        // 将时间模式注册到builder中
        jacksonObjectMapperBuilder.modulesToInstall(javaTimeModule);
    }
}